package com.cts.learninglibrary.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cts.learninglibrary.mapper.CommentMapper;
import com.cts.learninglibrary.mapper.UserMapper;
import com.cts.learninglibrary.pojo.Comment;
import com.cts.learninglibrary.pojo.User;
import com.cts.learninglibrary.service.CommentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: kwanghuee
 * @date: 2020/8/18 9:59
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    public UserMapper userMapper;

    /**
     * 二级树形展示评论
     * @param share_id
     * @return
     */
    @Override
    public List<Comment> listWithTree(Integer share_id) {
        //1.查询出share_id下的所有评论
        QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
        commentQueryWrapper.eq("share_id",share_id);
        List<Comment> comments = baseMapper.selectList(commentQueryWrapper);

        //2.得到以根评论为头的树形评论
        List<Comment> collect = comments.stream().filter(comment ->
                comment.getParentId() == -1
        ).peek(menu -> menu.setChildren(getChildrens(menu,comments))
        ).collect(Collectors.toList());

        combineChildren(collect);

        //给根评论添加评论昵称
        collect.stream(
        ).peek(comment -> comment.setNickname(userMapper.selectOne(new QueryWrapper<User>().eq("id",comment.getUserId())).getNickname())
        ).collect(Collectors.toList());

        return collect;
    }

    /**
     * 发送评论
     * @param comment
     */
    @Override
    public void reply(Comment comment) {
        commentMapper.insert(comment);
    }

    /**
     *
     * @param pageNo
     * @param pageSize
     * @param share_id
     * @return
     */
    @Override
    public Page<Comment> listWithTreeByPage(Integer pageNo, Integer pageSize, Integer share_id) {
        //处理得到需要进行分页的List
        //1.查询出share_id下的所有评论
        QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
        commentQueryWrapper.eq("share_id",share_id);
        List<Comment> comments = baseMapper.selectList(commentQueryWrapper);

        //2.把不是父评论的子评论装起来
        List<Comment> collect = comments.stream().filter(comment ->
                comment.getParentId() == -1
        ).peek(menu -> menu.setChildren(getChildrens(menu,comments))
        ).collect(Collectors.toList());

        combineChildren(collect);

        //给根评论添加评论昵称
        collect.stream().peek(comment ->
                comment.setNickname(userMapper.selectOne(new QueryWrapper<User>().eq("id",comment.getUserId())).getNickname())
        ).collect(Collectors.toList());

        //进行分页处理
        //当前页
        int current = pageNo;
        //每页数据条数
        int size = pageSize;
        Page<Comment> page = new Page<>(current,size);
        int count = collect.size();
        List<Comment> pageList = new ArrayList<>();
        //计算当前页第一条数据的下标
        int currId = current>1 ? (current-1)*size:0;
        for (int i=0; i<size && i<count - currId;i++){
            pageList.add(collect.get(currId+i));
        }
        page.setSize(size);
        page.setCurrent(current);
        page.setTotal(count);
        //计算分页总页数
        page.setPages(count %10 == 0 ? count/10 :count/10+1);
        page.setRecords(pageList);

        return page;
    }

    @Override
    public void deleteComment(Integer id) {
        commentMapper.deleteById(id);
    }

    /**
     * 递归得到树形评论
     * @param menu
     * @param all
     * @return
     */
    private List<Comment> getChildrens(Comment menu, List<Comment> all) {
        List<Comment> children = all.stream(
        //筛选出所有子评论 （本条评论的id等于其他评论的父id）
        ).filter(comment -> Objects.equals(comment.getParentId(), menu.getId())
        //递归 找出下一级评论的子评论
        ).peek(comment -> { comment.setChildren(getChildrens(comment,all));}
        //给当前子评论添加昵称
        ).peek(comment -> comment.setNickname(userMapper.selectOne(new QueryWrapper<User>().eq("id",comment.getUserId())).getNickname())
        //给当前子评论添加被回复用户的昵称
        ).peek(comment -> {
                    //1.先根据parent_id找到相关评论
                    Comment comment1 = commentMapper.selectById(comment.getParentId());
                    //2.根据相关评论找到user_id
                    User user = userMapper.selectById(comment1.getUserId());
                    comment.setReviewedNickname(user.getNickname());
            }
        //根据时间排序
        ).sorted(Comparator.comparing(Comment::getOperateTime)
        ).collect(Collectors.toList());
        return children;
    }

    /**
     *
     * @param comments root根节点，blog不为空的对象集合
     * @return
     */
    public static void combineChildren(List<Comment> comments) {

        for (Comment comment : comments) {
            List<Comment> replys1 = comment.getChildren();
            for(Comment reply1 : replys1) {
                //循环迭代，找出子代，存放在tempReplys中
                recursively(reply1);
            }

            //设置评论的子评论为空
            tempReplys.stream(
                    ).peek(menu -> menu.setChildren(null)
                    ).collect(Collectors.toList());

            //修改顶级节点的reply集合为迭代处理后的集合
            comment.setChildren(tempReplys);
            //清除临时存放区
            tempReplys = new ArrayList<>();
        }
    }

    //存放迭代找出的所有子代的集合
    private static List<Comment> tempReplys = new ArrayList<>();


    /**
     * 2级评论进行迭代，将包括二级评论顶节点放入临时集合中
     * @param comment
     */
    private static void recursively(Comment comment)  {
        tempReplys.add(comment);//顶节点添加到临时存放集合
        getChildrenComment(comment);
    }

    /**
     * 3级以及以上的评论进行迭代，将评论的子评论加入
     * @param comment
     */
    private static void recursivelyed(Comment comment) {
        getChildrenComment(comment);
    }

    /**
     * 递归迭代，剥洋葱
     * @param comment 被迭代的对象
     * @return
     */
    private static void getChildrenComment(Comment comment) {
        if (comment.getChildren().size()>0) {
            List<Comment> replys = comment.getChildren();
            for (Comment reply : replys) {

                tempReplys.add(reply);
                if (reply.getChildren().size()>0) {
                    recursivelyed(reply);
                }
            }
        }
    }
}